// @author U099151W Sun Chenchen
// all functions in this file  are implemented by the author unless specifically indicated
function WIMF_Start(UI_canvas, background_canvas, game_canvas, progress_bar_canvas) {
    gameEngine.init(UI_canvas, background_canvas, game_canvas, progress_bar_canvas);
    gameEngine.load();
}

/* GLOBAL VARIABLES */
var TILE_MAP = {
    ROWS : 10,
    COLS : 10,
    GRIDS : []
}
var TILE_RESOLUTION = 20;
var FIGHT_MODE = 0;
var FIGHT_ACTIVE = 0;
var DEBUG_MODE = false;
var DEBUG_MODE_INFO = false;
var DEBUG_MODE_STOP_GAME = 0;

// Define Weights for each action
// Action codes: 0 = punch, 1 = kick, 2 = block punch, 3 = jump to avoid kick
var SCORE_TABLE = [[0, 0, 0, 10], [0, 0, 10, 0], [10, 0, 0, 0], [0, 10, 0, 0]];
var SCORE_TABLE_HARD = [[10, 0, 0, 10], [0, 10, 10, 0], [10, 0, 0, 0], [0, 10, 0, 0]];
var FIGHT_INACTIVE = -1;
var PUNCH_CODE = 0;
var KICK_CODE = 1;
var BLOCK_CODE = 2;
var JUMP_CODE = 3;

var _gameEnd = false;
var _gameWin = false;

function setDebugMode() { DEBUG_MODE = true; };
function clearDebugMode() { DEBUG_MODE = false; };
function setDebugModeInfo() { DEBUG_MODE_INFO = true; };
function clearDebugModeInfo() { DEBUG_MODE_INFO = false; };
var _inverseFPS = 1.0/30.0;

function GameEngine() {
    // to enforce singleton
    if ( arguments.callee._singletonInstance )
        return arguments.callee._singletonInstance;
    arguments.callee._singletonInstance = this;

    var _UI_canvas = null;
    var _background_canvas = null;
    var _game_canvas = null;
    var _progress_bar_canvas = null;

    var _scene = null;
    var _frameNumber = 0;
    var _renderIntervalHandler;

    var _collisionMargin = 5;
    var _walkVerticalYMargin = 0;
    var _walkVerticalXMargin = 0;
    var _walkHorizontalXMargin = 1;
    var _walkHorizontalYMargin = 1;
    var _punchXMargin = 1.2;
    var _punchYMargin = 1;
    var _kickXMargin = 2;
    var _kickYMargin = 1;
    var _specialAttackMarginX = 5;
    var _specialAttackMarginY = 5;
    var _NPCTimer = 1;

    var _ai_slowDown = 1;
    var _ai_count = 0;

    this.createScene = function() {
        return ai.createScene();
    }

    this.init = function(UI_canvas, background_canvas, game_canvas, progress_bar_canvas) {
        _UI_canvas = document.getElementById(UI_canvas);
        _background_canvas = document.getElementById(background_canvas);
        _game_canvas = document.getElementById(game_canvas);
        _progress_bar_canvas = document.getElementById(progress_bar_canvas);

        graphicEngine.init(_inverseFPS, _UI_canvas, _background_canvas, _game_canvas, _progress_bar_canvas)
        inputManager.init(_inverseFPS, _game_canvas);
        normalFightSystem.init(SCORE_TABLE);
        hardFightSystem.init(SCORE_TABLE_HARD);
        ai.init(_game_canvas);
        document.getElementById("start_button").onclick = gameEngine.runDebug;
    }

    this.load = function() {
        graphicEngine.load();
        _scene = this.createScene();
        graphicEngine.setScene(_scene);
        inputManager.setScene(_scene);
        ai.setScene(_scene);
        this.setDebug();
    }

    this.run = function() {
        _frameNumber++;
        var clock = new Date();
        var frameStartTime = clock.getTime();

        if (!DEBUG_MODE_STOP_GAME) {
            ////////////////////////////////////////
            // Game Loop Here
            // input manager should run at a much slower speed
            inputManager.processEntry() ;

            if (_ai_count < _ai_slowDown) {
                _ai_count++
            } else {
                _ai_count = 0;
                ai.update();
            }
            gameEngine.update(_inverseFPS);
            graphicEngine.render() ;
            ////////////////////////////////////////
        }


        // Calculate the time until next frame;
        clock = new Date() ;
        var frameEndTime = clock.getTime();
        var timeLeft = _inverseFPS - ((frameEndTime - frameStartTime)/1000.0);// Used time for frame execution

        var nextFrameTime =  (( timeLeft < 0 )? 0 :((timeLeft > _inverseFPS)? _inverseFPS :timeLeft));
        //console.log(nextFrameTime);
        if (!_gameEnd && !_gameWin)
            setTimeout(gameEngine.run, nextFrameTime*1000 );
        return;
    }

    function checkCollision(direction, a, b, marginX, marginY) {
        if (direction === "up") {
            var dy = a.y - b.y;
            var dx = Math.abs(a.x - b.x);
            if ( dy < marginY * TILE_RESOLUTION && dy > 0 &&
                dx < marginX * TILE_RESOLUTION) {
                return true;
            }
            return false;
        }
        else if (direction === "down") {
            var dy = b.y - a.y;
            var dx = Math.abs(a.x - b.x);
            if ( dy < marginY * TILE_RESOLUTION && dy > 0 &&
                dx < marginX * TILE_RESOLUTION) {
                return true;
            }
            return false;
        }
        else if (direction === "left") {
            var dy = Math.abs(a.y - b.y);
            var dx = a.x - b.x;
            if ( dx < marginX * TILE_RESOLUTION && dx > 0 &&
                dy < marginY * TILE_RESOLUTION) {
                return true;
            }
            return false;
        }
        else if (direction === "right") {
            var dy = Math.abs(a.y - b.y);
            var dx = b.x - a.x;
            if ( dx < marginX * TILE_RESOLUTION && dx > 0 &&
                dy < marginY * TILE_RESOLUTION) {
                return true;
            }
            return false;
        }
        return false;
    }

    // @author U095159L VARUN GANESH and U099151W Sun Chenchen
    this.update = function(_inverseFPS) {

        hardFightSystem.update(FIGHT_MODE);
        // update player and character state
        // PLAYER
        var targetIdList = [];
        // first find out all characters might be affected
        for (var i=0; i<_scene.Student.length; i++) {
            _scene.Student[i].nextState =_scene.Student[i].state;
            //_scene.Student[i].clearGrid();
            if (Math.abs(_scene.Student[i].x - _scene.Player.x) / TILE_RESOLUTION < _collisionMargin ||
                Math.abs(_scene.Student[i].x - _scene.Player.x) / TILE_RESOLUTION < _collisionMargin)
            {
                targetIdList.push(i);

            }
        }
        for (var i=0; i<_scene.Professor.length; i++) {
            _scene.Professor[i].nextState =_scene.Professor[i].state;
        }
        for (var i=0; i<_scene.Guard.length; i++) {
            _scene.Guard[i].nextState =_scene.Guard[i].state;
        }

        // TEMP
        _scene.Player.nextState = _scene.Player.state;
        // TEMP
        var player = _scene.Player;
        switch (player.state) {
            //attack player if he is still
            case "stillLeft":
            case "stillRight":
                if(FIGHT_ACTIVE == 1){

                    var rand = Math.floor(Math.random()*2);
                    if(rand == 0){
                        FIGHT_MODE = JUMP_CODE;
                    }
                    if(rand == 1){
                        FIGHT_MODE = BLOCK_CODE;
                    }

                    _NPCTimer++;
                    if(parseInt(_NPCTimer)%10== 0){
                        console.log("update", FIGHT_MODE);
                        normalFightSystem.update(FIGHT_MODE);
                    }
                }
                break;

            case "hitTopFrontLeft":
            case "hitTopBackLeft":
            case "hitMidFrontLeft":
            case "hitMidBackLeft":
            case "hitLowFrontLeft":
            case "hitLowBackLeft":
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillLeft";
                }
                player.moveRight();
                break;

            case "hitTopFrontRight":
            case "hitTopBackRight":
            case "hitMidFrontRight":
            case "hitMidBackRight":
            case "hitLowFrontRight":
            case "hitLowBackRight":
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillRight";
                }
                player.moveLeft();
                break;

            case "walkUpRight" :
                var inCollision = false;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillRight";
                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if(checkCollision("up", player, _scene.Student[id], _walkVerticalXMargin, _walkVerticalYMargin)) {
                        inCollision = true;
                        _scene.Player.nextState = "stillRight";
                        break;
                    }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    var guard = _scene.Guard[i];
                    if(checkCollision("up", player, guard, _walkVerticalXMargin, _walkVerticalYMargin)) {
                        inCollision = true;
                        _scene.Player.nextState = "stillRight";
                        break;
                    }
                }
                if (inCollision)
                    break;
                if (TILE_MAP.GRIDS[player.tileY - 1][player.tileX] == 1)
                    break;
                player.moveUp();
                break;
            case "walkUpLeft" :
                var inCollision = false;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillLeft";
                }

                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if(checkCollision("up", player, _scene.Student[id], _walkVerticalXMargin, _walkVerticalYMargin)) {
                        inCollision = true;
                        _scene.Player.nextState = "stillLeft";
                        break;
                    }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    var guard = _scene.Guard[i];
                    if(checkCollision("up", player, guard, _walkVerticalXMargin, _walkVerticalYMargin)) {
                        inCollision = true;
                        _scene.Player.nextState = "stillLeft";
                        break;
                    }
                }
                if (inCollision)
                    break;
                if (TILE_MAP.GRIDS[player.tileY - 1][player.tileX] == 1)
                    break;
                player.moveUp();
                break;
            case "walkDownRight" :
                var inCollision = false;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillRight";
                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if(checkCollision("down", player, _scene.Student[id], _walkVerticalXMargin, _walkVerticalYMargin)) {
                        inCollision = true;
                        _scene.Player.nextState = "stillRight";
                        break;
                    }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    var guard = _scene.Guard[i];
                    if(checkCollision("down", player, guard, _walkVerticalXMargin, _walkVerticalYMargin)) {
                        inCollision = true;
                        _scene.Player.nextState = "stillRight";
                        break;
                    }
                }
                if (inCollision)
                    break;
                if (TILE_MAP.GRIDS[player.tileY + 1][player.tileX] == 1)
                    break;
                player.moveDown();
                break;
            case "walkDownLeft" :
                var inCollision = false;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillLeft";
                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if(checkCollision("down", player, _scene.Student[id], _walkVerticalXMargin, _walkVerticalYMargin)) {
                        inCollision = true;
                        _scene.Player.nextState = "stillLeft";
                        break;
                    }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    var guard = _scene.Guard[i];
                    if(checkCollision("down", player, guard, _walkVerticalXMargin, _walkVerticalYMargin)) {
                        inCollision = true;
                        _scene.Player.nextState = "stillLeft";
                        break;
                    }
                }
                if (inCollision)
                    break;
                if (TILE_MAP.GRIDS[player.tileY + 1][player.tileX] == 1)
                    break;
                player.moveDown();
                break;
            case "walkLeft" :
                var inCollision = false;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillLeft";
                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if(checkCollision("left", player, _scene.Student[id], _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        _scene.Player.nextState = "stillLeft";
                        break;
                    }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    var guard = _scene.Guard[i];
                    if(checkCollision("left", player, guard, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        _scene.Player.nextState = "stillLeft";
                        break;
                    }
                }
                if (inCollision)
                    break;
                if (TILE_MAP.GRIDS[player.tileY][player.tileX -1] == 1)
                    break;
                player.moveLeft();
                break;
            case "walkRight" :
                var inCollision = false;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillRight";
                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if(checkCollision("right", player, _scene.Student[id], _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        _scene.Player.nextState = "stillRight";
                        break;
                    }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    var guard = _scene.Guard[i];
                    if(checkCollision("right", player, guard, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        _scene.Player.nextState = "stillRight";
                        break;
                    }
                }

                if (inCollision)
                    break;
                if (TILE_MAP.GRIDS[player.tileY][player.tileX + 1] == 1)
                    break;
                player.moveRight();
                break;
            case "jumpLeft" :
                FIGHT_MODE = JUMP_CODE;
                if (player.currentSpriteFrame < player.sprites[player.state].length/2) {
                    player.moveUp();
                    player.moveUp();
                }
                else {
                    player.moveDown();
                    player.moveDown();
                }
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillLeft";
                    console.log("update", FIGHT_MODE);
                    normalFightSystem.update(FIGHT_MODE);
                }


                break;
            case "jumpRight" :
                FIGHT_MODE = JUMP_CODE;
                // [TODO] does not jump back to ground of the same height
                if (player.currentSpriteFrame < player.sprites[player.state].length/2) {
                    player.moveUp();
                    player.moveUp();
                }
                else {
                    player.moveDown();
                    player.moveDown();
                }
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillRight";
                    console.log("update", FIGHT_MODE);
                    normalFightSystem.update(FIGHT_MODE);

                }
                break;
            case "specialLeft" :

                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillLeft";
                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame) {
                        if(checkCollision("left", player, _scene.Student[id], _specialAttackMarginX, _specialAttackMarginY)) {
                            if (_scene.Student[id].state.indexOf("block") === -1) {
                                _scene.Student[id].nextState = "hitMidFrontRight";
                                _scene.Student[id].health -= 50;
                            }
                        }
                        if(checkCollision("right", player, _scene.Student[id], _specialAttackMarginX, _specialAttackMarginY)) {
                            if (_scene.Student[id].state.indexOf("block") === -1) {
                                _scene.Student[id].nextState = "hitMidFrontLeft";
                                _scene.Student[id].health -= 100;
                                if (_scene.Student[id].health < 0)
                                    _scene.Student[id].health = 0;
                            }
                        }
                    }
                }
                break;
            case "punchLeft" :
                FIGHT_MODE = PUNCH_CODE;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillLeft";
                    console.log("update", FIGHT_MODE);
                    normalFightSystem.update(FIGHT_MODE);

                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("left", player, _scene.Student[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (_scene.Student[id].state.indexOf("block") === -1) {
                                _scene.Student[id].nextState = "hitMidFrontRight";
                                _scene.Student[id].health -= 50;
                                player.addCombo();
                                break;
                            }

                        }
                }
                for (var i=0; i<_scene.Professor.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("left", player, _scene.Professor[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (_scene.Professor[id].state.indexOf("block") === -1) {
                                _scene.Professor[id].nextState = "hitMidFrontRight";
                                _scene.Professor[id].health -= 50;
                                break;
                            }

                        }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("left", player, _scene.Guard[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (_scene.Guard[id].state.indexOf("block") === -1) {
                                _scene.Guard[id].nextState = "hitMidFrontRight";
                                _scene.Guard[id].health -= 50;
                                break;
                            }

                        }
                }
                break;
            case "punchRight" :
                FIGHT_MODE = PUNCH_CODE;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillRight";
                    console.log("update", FIGHT_MODE);
                    normalFightSystem.update(FIGHT_MODE);
                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("right", player, _scene.Student[id], _punchXMargin, _punchYMargin)) {
                            if (_scene.Student[id].state.indexOf("block") === -1) {
                                _scene.Student[id].nextState = "hitMidFrontLeft";
                                _scene.Student[id].health -= 50;
                                player.addCombo();
                                break;
                            }
                        }
                }
                for (var i=0; i<_scene.Professor.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("right", player, _scene.Professor[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (_scene.Professor[id].state.indexOf("block") === -1) {
                                _scene.Professor[id].nextState = "hitMidFrontLeft";
                                _scene.Professor[id].health -= 50;
                                break;
                            }

                        }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("right", player, _scene.Guard[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (_scene.Guard[id].state.indexOf("block") === -1) {
                                _scene.Guard[id].nextState = "hitMidFrontLeft";
                                _scene.Guard[id].health -= 50;
                                break;
                            }

                        }
                }
                break;
            case "kickHighRight" :
                FIGHT_MODE = BLOCK_CODE;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillRight";
                    normalFightSystem.update(FIGHT_MODE);
                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("right", player, _scene.Student[id], _kickXMargin, _kickYMargin)) {
                            if (_scene.Student[id].state.indexOf("block") === -1) {
                                _scene.Student[id].nextState = "hitTopFrontLeft";
                                _scene.Student[id].health -= 50;
                                player.addCombo();
                                break;
                            }
                        }
                }
                for (var i=0; i<_scene.Professor.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("right", player, _scene.Professor[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (_scene.Professor[id].state.indexOf("block") === -1) {
                                _scene.Professor[id].nextState = "hitTopFrontLeft";
                                _scene.Professor[id].health -= 50;
                                break;
                            }

                        }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("right", player, _scene.Guard[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (_scene.Guard[id].state.indexOf("block") === -1) {
                                _scene.Guard[id].nextState = "hitTopFrontLeft";
                                _scene.Guard[id].health -= 50;
                                break;
                            }

                        }
                }
                break;
            case "kickHighLeft" :
                FIGHT_MODE = PUNCH_CODE;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillLeft";
                    normalFightSystem.update(FIGHT_MODE);
                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("left", player, _scene.Student[id], _kickXMargin, _kickYMargin)) {
                            if (_scene.Student[id].state.indexOf("block") === -1) {
                                _scene.Student[id].nextState = "hitTopFrontRight";
                                _scene.Student[id].health -= 50;
                                player.addCombo();
                                break;
                            }
                        }
                }
                for (var i=0; i<_scene.Professor.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("left", player, _scene.Professor[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (_scene.Professor[id].state.indexOf("block") === -1) {
                                _scene.Professor[id].nextState = "hitTopFrontRight";
                                _scene.Professor[id].health -= 50;
                                break;
                            }

                        }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("left", player, _scene.Guard[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (_scene.Guard[id].state.indexOf("block") === -1) {
                                _scene.Guard[id].nextState = "hitTopFrontRight";
                                _scene.Guard[id].health -= 50;
                                break;
                            }

                        }
                }
                break;
            case "kickMidRight" :
                FIGHT_MODE = PUNCH_CODE;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillRight";
                    console.log("update", FIGHT_MODE);
                    normalFightSystem.update(FIGHT_MODE);
                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("right", player, _scene.Student[id], _kickXMargin, _kickYMargin)) {
                            if (_scene.Student[id].state.indexOf("block") === -1) {
                                _scene.Student[id].nextState = "hitMidFrontLeft";
                                _scene.Student[id].health -= 50;
                                player.addCombo();
                                break;
                            }
                        }
                }
                for (var i=0; i<_scene.Professor.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("right", player, _scene.Professor[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (_scene.Professor[id].state.indexOf("block") === -1) {
                                _scene.Professor[id].nextState = "hitMidFrontLeft";
                                _scene.Professor[id].health -= 50;
                                break;
                            }

                        }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("right", player, _scene.Guard[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (_scene.Guard[id].state.indexOf("block") === -1) {
                                _scene.Guard[id].nextState = "hitMidFrontLeft";
                                _scene.Guard[id].health -= 50;
                                break;
                            }

                        }
                }
                break;
            case "kickMidLeft" :
                FIGHT_MODE = PUNCH_CODE;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillLeft";
                    console.log("update", FIGHT_MODE);
                    normalFightSystem.update(FIGHT_MODE);
                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("left", player, _scene.Student[id], _kickXMargin, _kickYMargin)) {
                            if (_scene.Student[id].state.indexOf("block") === -1) {
                                _scene.Student[id].nextState = "hitMidFrontRight";
                                _scene.Student[id].health -= 50;
                                player.addCombo();
                                break;
                            }
                        }
                }
                for (var i=0; i<_scene.Professor.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("left", player, _scene.Professor[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (_scene.Professor[id].state.indexOf("block") === -1) {
                                _scene.Professor[id].nextState = "hitMidFrontRight";
                                _scene.Professor[id].health -= 50;
                                break;
                            }

                        }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("left", player, _scene.Guard[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (_scene.Guard[id].state.indexOf("block") === -1) {
                                _scene.Guard[id].nextState = "hitMidFrontRight";
                                _scene.Guard[id].health -= 50;
                                break;
                            }

                        }
                }
                break;
            case "kickLowRight" :
                FIGHT_MODE = KICK_CODE;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillRight";
                    console.log("update", FIGHT_MODE);
                    normalFightSystem.update(FIGHT_MODE);
                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("right", player, _scene.Student[id], _kickXMargin, _kickYMargin)) {
                            _scene.Student[id].nextState = "hitLowFrontLeft";
                            _scene.Student[id].health -= 50;

                            break;
                        }
                }
                for (var i=0; i<_scene.Professor.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("right", player, _scene.Professor[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            _scene.Professor[id].nextState = "hitLowFrontLeft";
                            _scene.Professor[id].health -= 50;
                            break;

                        }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("right", player, _scene.Guard[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            _scene.Guard[id].nextState = "hitLowFrontLeft";
                            _scene.Guard[id].health -= 50;
                            break;

                        }
                }
                break;
            case "kickLowLeft" :
                FIGHT_MODE = KICK_CODE;
                if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                    player.currentSpriteFrame = 0;
                    _scene.Player.nextState = "stillLeft";
                    console.log("update", FIGHT_MODE);
                    normalFightSystem.update(FIGHT_MODE);
                }
                for (var i=0; i<targetIdList.length; i++) {
                    var id = targetIdList[i];
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("left", player, _scene.Student[id], _kickXMargin, _kickYMargin)) {
                            _scene.Student[id].nextState = "hitLowFrontRight";
                            _scene.Student[id].health -= 50;

                            break;
                        }
                }
                for (var i=0; i<_scene.Professor.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("left", player, _scene.Professor[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            _scene.Professor[id].nextState = "hitLowFrontRight";
                            _scene.Professor[id].health -= 50;
                            break;

                        }
                }
                for (var i=0; i<_scene.Guard.length; i++) {
                    id = i;
                    if (player.currentSpriteFrame == player.sprites[player.state].critFrame)
                        if(checkCollision("left", player, _scene.Guard[id], _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            _scene.Guard[id].nextState = "hitLowFrontRight";
                            _scene.Guard[id].health -= 50;
                            break;

                        }
                }
                break;
            case "blockLeft" :
                FIGHT_MODE = BLOCK_CODE;
                if (player.blocking) {
                    if (player.currentSpriteFrame >= player.sprites[player.state].critFrame) {
                        player.currentSpriteFrame = player.sprites[player.state].critFrame;
                        _NPCTimer++;
                        if(parseInt(_NPCTimer)%15== 0){
                            normalFightSystem.update(FIGHT_MODE);
                        }
                    }
                }
                else {
                    if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                        player.currentSpriteFrame = 0;
                        _scene.Player.nextState = "stillLeft";
                    }
                }

            case "blockRight" :
                FIGHT_MODE = BLOCK_CODE;
                if (player.blocking) {
                    if (player.currentSpriteFrame >= player.sprites[player.state].critFrame) {
                        player.currentSpriteFrame = player.sprites[player.state].critFrame;
                        _NPCTimer++;
                        if(parseInt(_NPCTimer)%15== 0){
                            normalFightSystem.update(FIGHT_MODE);
                        }
                    }
                }
                else {
                    if (player.currentSpriteFrame == player.sprites[player.state].length-1) {
                        player.currentSpriteFrame = 0;
                        _scene.Player.nextState = "stillRight";
                        console.log("update", FIGHT_MODE);

                    }
                }
            default :
                break;
        }


        for (var i=0; i < _scene.Student.length; i++) {
            var student = _scene.Student[i];

            switch (student.state) {
                case "hitTopFrontLeft":
                case "hitTopBackLeft":
                case "hitMidFrontLeft":
                case "hitMidBackLeft":
                case "hitLowFrontLeft":
                case "hitLowBackLeft":
                    if (student.health <=0) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "deathRight";
                    }

                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillLeft";
                    }
                    student.moveRight();
                    student.moveRight();
                    student.moveRight();
                    break;

                case "hitTopFrontRight":
                case "hitTopBackRight":
                case "hitMidFrontRight":
                case "hitMidBackRight":
                case "hitLowFrontRight":
                case "hitLowBackRight":
                    if (student.health <=0) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "deathRight";
                    }

                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillRight";
                    }
                    student.moveLeft();
                    student.moveLeft();
                    student.moveLeft();
                    break;


                case "walkUpRight" :
                    var inCollision = false;
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillRight";
                    }
                    if(checkCollision("up", student, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    student.moveUp();
                    break;
                case "walkUpLeft" :
                    var inCollision = false;
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillLeft";
                    }
                    if(checkCollision("up", student, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    student.moveUp();
                    break;
                case "walkDownRight" :
                    var inCollision = false;
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillRight";
                    }
                    if(checkCollision("down", student, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    student.moveDown();
                    break;
                case "walkDownLeft" :
                    var inCollision = false;
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillLeft";
                    }
                    if(checkCollision("down", student, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    student.moveDown();
                    break;
                case "walkLeft" :
                    var inCollision = false;
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillLeft";
                    }
                    if(checkCollision("left", student, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    student.moveLeft();
                    break;
                case "walkRight" :
                    var inCollision = false;
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillRight";
                    }
                    if(checkCollision("right", student, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    student.moveRight();
                    break;
                case "jumpLeft" :
                    if (student.currentSpriteFrame < student.sprites[student.state].length/2) {
                        student.moveUp();
                        student.moveUp();
                        student.moveUp();
                    }
                    else {
                        student.moveDown();
                        student.moveDown();
                        student.moveDown();
                    }
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillLeft";
                    }

                    break;
                case "jumpRight" :
                    if (student.currentSpriteFrame < student.sprites[student.state].length/2) {
                        student.moveUp();
                        student.moveUp();
                        student.moveUp();
                    }
                    else {
                        student.moveDown();
                        student.moveDown();
                        student.moveDown();
                    }
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillRight";
                    }

                    break;
                case "punchLeft" :
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillLeft";
                    }
                    if (student.currentSpriteFrame == student.sprites[student.state].critFrame)
                        if(checkCollision("left", student, player, _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (player.state != "blockRight" && player.state != "specialLeft" )
                                player.nextState = "hitMidFrontRight";
                            else {
                                if (player.state == "blockLeft")
                                    player.updateState("stillRight")
                            }

                            break;
                        }
                    break;
                case "punchRight" :
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillRight";
                    }
                    if (student.currentSpriteFrame == student.sprites[student.state].critFrame)
                        if(checkCollision("right", student, player, _punchXMargin, _punchYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (player.state != "blockLeft" && player.state != "specialLeft" )
                                player.nextState = "hitMidFrontLeft";
                            else {
                                if (player.state == "blockLeft")
                                    player.updateState("stillLeft")
                            }
                            break;
                        }
                    break;
                case "kickHighRight" :
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillRight";
                    }
                    if (student.currentSpriteFrame == student.sprites[student.state].critFrame)
                        if(checkCollision("right", student, player, _kickXMargin, _kickYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (player.state != "blockLeft" && player.state != "specialLeft" )
                                player.nextState = "hitTopFrontLeft";
                            else {
                                if (player.state == "blockLeft")
                                    player.updateState("stillRight")
                            }
                            break;
                        }
                    break;
                case "kickHighLeft" :
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillLeft";
                    }
                    if (student.currentSpriteFrame == student.sprites[student.state].critFrame)
                        if(checkCollision("left", student, player, _kickXMargin, _kickYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if ( player.state != "blockRight" && player.state != "specialLeft" )
                                player.nextState = "hitTopFrontRight";
                            else {
                                if (player.state == "blockLeft")
                                    player.updateState("stillLeft")
                            }
                            break;
                        }
                    break;
                case "kickMidRight" :
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillRight";
                    }
                    if (student.currentSpriteFrame == student.sprites[student.state].critFrame)
                        if(checkCollision("right", student, player, _kickXMargin, _kickYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (player.state != "blockLeft" && player.state != "specialLeft" )
                                player.nextState = "hitMidFrontLeft";
                            else {
                                if (player.state == "blockLeft")
                                    player.updateState("stillRight")
                            }
                            break;
                        }
                    break;
                case "kickMidLeft" :
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillLeft";
                    }
                    if (student.currentSpriteFrame == student.sprites[student.state].critFrame)
                        if(checkCollision("left", student, player, _kickXMargin, _kickYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            if (player.state != "blockRight" && player.state != "specialLeft" )
                                player.nextState = "hitMidFrontRight";
                            else {

                                player.updateState("stillLeft")
                            }
                            break;
                        }
                    break;
                case "kickLowRight" :
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillRight";
                    }
                    if (student.currentSpriteFrame == student.sprites[student.state].critFrame)
                        if(checkCollision("right", student, player, _kickXMargin, _kickYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            player.nextState = "hitLowFrontLeft";
                            break;
                        }
                    break;
                case "kickLowLeft" :
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.nextState = "stillLeft";
                    }
                    if (student.currentSpriteFrame == student.sprites[student.state].critFrame)
                        if(checkCollision("left", student, player, _kickXMargin, _kickYMargin)) {
                            // [TODO] depend on the facing of the enemy
                            player.nextState = "hitLowFrontRight";
                            break;
                        }
                    break;
                case "deathRight":
                case "deathLeft" :
                    if (student.currentSpriteFrame == student.sprites[student.state].length-1) {
                        student.currentSpriteFrame = 0;
                        student.alive = false;
                        _scene.Student.splice(i, 1);
                        student.clearGrid();
                        player.addFood(student.foodAmount);
                    }
                    break;
                default :
                    break;
            }
        }

        for (var i=0; i < _scene.Guard.length; i++) {
            var guard = _scene.Guard[i];
            switch (guard.state) {
                case "hitTopFrontLeft":
                case "hitTopBackLeft":
                case "hitMidFrontLeft":
                case "hitMidBackLeft":
                case "hitLowFrontLeft":
                case "hitLowBackLeft":
                    if (guard.health <=0) {
                        guard.currentSpriteFrame = 0;
                        guard.nextState = "deathRight";
                    }

                    if (guard.currentSpriteFrame == guard.sprites[guard.state].length-1) {
                        guard.currentSpriteFrame = 0;
                        guard.nextState = "stillLeft";
                    }

                    break;

                case "hitTopFrontRight":
                case "hitTopBackRight":
                case "hitMidFrontRight":
                case "hitMidBackRight":
                case "hitLowFrontRight":
                case "hitLowBackRight":
                    if (guard.health <=0) {
                        guard.currentSpriteFrame = 0;
                        guard.nextState = "deathRight";
                    }

                    if (guard.currentSpriteFrame == guard.sprites[guard.state].length-1) {
                        guard.currentSpriteFrame = 0;
                        guard.nextState = "stillRight";
                    }

                    break;

                case "runUpRight" :
                    var inCollision = false;
                    if (guard.currentSpriteFrame == guard.sprites[guard.state].length-1) {
                        guard.currentSpriteFrame = 0;
                        guard.nextState = "stillRight";
                    }
                    if(checkCollision("up", guard, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    guard.moveUp();
                    break;
                case "runUpLeft" :
                    var inCollision = false;
                    if (guard.currentSpriteFrame == guard.sprites[guard.state].length-1) {
                        guard.currentSpriteFrame = 0;
                        guard.nextState = "stillLeft";
                    }
                    if(checkCollision("up", guard, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    guard.moveUp();
                    break;
                case "runDownRight" :
                    var inCollision = false;
                    if (guard.currentSpriteFrame == guard.sprites[guard.state].length-1) {
                        guard.currentSpriteFrame = 0;
                        guard.nextState = "stillRight";
                    }
                    if(checkCollision("down", guard, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    guard.moveDown();
                    break;
                case "runDownLeft" :
                    var inCollision = false;
                    if (guard.currentSpriteFrame == guard.sprites[guard.state].length-1) {
                        guard.currentSpriteFrame = 0;
                        guard.nextState = "stillLeft";
                    }
                    if(checkCollision("down", guard, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    guard.moveDown();
                    break;
                case "runLeft" :
                    var inCollision = false;
                    if (guard.currentSpriteFrame == guard.sprites[guard.state].length-1) {
                        guard.currentSpriteFrame = 0;
                        guard.nextState = "stillLeft";
                    }
                    if(checkCollision("left", guard, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    guard.moveLeft();
                    break;
                case "runRight" :
                    var inCollision = false;
                    if (guard.currentSpriteFrame == guard.sprites[guard.state].length-1) {
                        guard.currentSpriteFrame = 0;
                        guard.nextState = "stillRight";
                    }
                    if(checkCollision("right", guard, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    guard.moveRight();
                    break;
                case "deathRight":
                case "deathLeft" :
                    if (guard.currentSpriteFrame == guard.sprites[guard.state].length-1) {
                        guard.currentSpriteFrame = 0;
                        guard.alive = false;
                        for (var i=0; i < _scene.Guard.length; i++) {
                            _scene.Guard.splice(i, 1);
                            player.addFood(guard.foodAmount);
                        }


                    }
                    break;

                default:
                    break;
            }
        }

        for (var i=0; i < _scene.Professor.length; i++) {
            var professor = _scene.Professor[i];
            switch (professor.state) {
                case "hitTopFrontLeft":
                case "hitTopBackLeft":
                case "hitMidFrontLeft":
                case "hitMidBackLeft":
                case "hitLowFrontLeft":
                case "hitLowBackLeft":
                    if (professor.health <=0) {
                        professor.currentSpriteFrame = 0;
                        professor.nextState = "deathRight";
                    }

                    if (professor.currentSpriteFrame == professor.sprites[professor.state].length-1) {
                        professor.currentSpriteFrame = 0;
                        professor.nextState = "stillLeft";
                    }

                    break;

                case "hitTopFrontRight":
                case "hitTopBackRight":
                case "hitMidFrontRight":
                case "hitMidBackRight":
                case "hitLowFrontRight":
                case "hitLowBackRight":
                    if (professor.health <=0) {
                        professor.currentSpriteFrame = 0;
                        professor.nextState = "deathRight";
                    }

                    if (professor.currentSpriteFrame == professor.sprites[professor.state].length-1) {
                        professor.currentSpriteFrame = 0;
                        professor.nextState = "stillRight";
                    }

                    break;

                case "walkUpRight" :
                    var inCollision = false;
                    if (professor.currentSpriteFrame == professor.sprites[professor.state].length-1) {
                        professor.currentSpriteFrame = 0;
                        professor.nextState = "stillRight";
                    }
                    if(checkCollision("up", professor, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    professor.moveUp();
                    break;
                case "walkUpLeft" :
                    var inCollision = false;
                    if (professor.currentSpriteFrame == professor.sprites[professor.state].length-1) {
                        professor.currentSpriteFrame = 0;
                        professor.nextState = "stillLeft";
                    }
                    if(checkCollision("up", professor, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    professor.moveUp();
                    break;
                case "walkDownRight" :
                    var inCollision = false;
                    if (professor.currentSpriteFrame == professor.sprites[professor.state].length-1) {
                        professor.currentSpriteFrame = 0;
                        professor.nextState = "stillRight";
                    }
                    if(checkCollision("down", professor, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    professor.moveDown();
                    break;
                case "walkDownLeft" :
                    var inCollision = false;
                    if (professor.currentSpriteFrame == professor.sprites[professor.state].length-1) {
                        professor.currentSpriteFrame = 0;
                        professor.nextState = "stillLeft";
                    }
                    if(checkCollision("down", professor, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    professor.moveDown();
                    break;
                case "walkLeft" :
                    var inCollision = false;
                    if (professor.currentSpriteFrame == professor.sprites[professor.state].length-1) {
                        professor.currentSpriteFrame = 0;
                        professor.nextState = "stillLeft";
                    }
                    if(checkCollision("left", professor, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    professor.moveLeft();
                    break;
                case "walkRight" :
                    var inCollision = false;
                    if (professor.currentSpriteFrame == professor.sprites[professor.state].length-1) {
                        professor.currentSpriteFrame = 0;
                        professor.nextState = "stillRight";
                    }
                    if(checkCollision("right", professor, player, _walkHorizontalXMargin, _walkHorizontalYMargin)) {
                        inCollision = true;
                        break;
                    }
                    if (inCollision)
                        break;
                    professor.moveRight();
                    break;
                case "deathRight":
                case "deathLeft" :
                    if (professor.currentSpriteFrame == professor.sprites[professor.state].length-1) {
                        professor.currentSpriteFrame = 0;
                        professor.alive = false;
                        for (var i=0; i < _scene.Student.length; i++) {
                            var student = _scene.Student[i];
                            if (Math.abs(professor.tileX - student.tileX) < professor.effectRadius &&
                                Math.abs(professor.tileY - student.tileY) < professor.effectRadius )
                                student.slowedDown = 1;

                        }
                        if (Math.abs(professor.tileX - player.tileX) < professor.effectRadius &&
                            Math.abs(professor.tileY - player.tileY) < professor.effectRadius )
                            player.slowedDown = 1;
                        _scene.Professor.splice(i, 1);
                        player.addFood(professor.foodAmount);
                    }
                    break;

                default:
                    break;
            }
        }

        player.state = _scene.Player.nextState;
        for (var i=0; i<_scene.Student.length; i++) {
            //_scene.Student[i].updateGrid();
            _scene.Student[i].state = _scene.Student[i].nextState;
        }
        for (var i=0; i<_scene.Professor.length; i++) {
            //_scene.Student[i].updateGrid();
            _scene.Professor[i].state = _scene.Professor[i].nextState;
        }
        for (var i=0; i<_scene.Guard.length; i++) {
            //_scene.Student[i].updateGrid();
            _scene.Guard[i].state = _scene.Guard[i].nextState;
        }


        // update stage time
        _scene.Stages[_scene.currentStage].decreaseTime();

        // update player food
        _scene.Player.decreaseFood();
        if (_scene.Player.foodCount === 0)
            _scene.Player.state = "deathRight";

        // losing condition
        if (_scene.Stages[_scene.currentStage].timeLeft === 0 || _scene.Player.foodCount ===0 )
            _gameEnd = true;

        if (Math.floor(player.x / graphicEngine.getBackgroundImage().width * 100) > 90 )
            _gameWin = true;



        // update camera position
        camera.update(_scene);
    }

    // @author U095159L VARUN GANESH
    this.setDebug = function(){
        this.setDebugHelper("character_type", "choose_action", 1);
        this.setDebugHelper("NPC_type", "choose_action_NPC", 0);
    }

    // @author U095159L VARUN GANESH
    this.setDebugHelper = function( string1, string2, index){
        var spriteList = sceneDef.getCharacterSpriteList();
        var characterType = document.getElementById(string1);
        characterType.onchange = function() {
            var characterSelected = characterType.options[characterType.selectedIndex];
            var characterSprites = spriteList[characterSelected.text + "Sprites"];
            var actionType = document.getElementById(string2);
            for (var sprite in characterSprites) {
                var newOption = document.createElement('option');
                newOption.text = sprite;
                actionType.add(newOption);
            }
        };
        for (var obj in spriteList) {
            var objName = obj.split("Sprites")[0];
            var newOption = document.createElement('option');
            newOption.text = objName;
            characterType.add(newOption);
        }
        characterType.selectedIndex = index;
        var characterSelected = characterType.options[characterType.selectedIndex];
        var characterSprites = spriteList[characterSelected.text + "Sprites"];
        var actionType = document.getElementById(string2);
        for (var sprite in characterSprites) {
            var newOption = document.createElement('option');
            newOption.text = sprite;
            actionType.add(newOption);
        }

    };

    // @author U095159L VARUN GANESH
    this.runDebug = function(){
        var characterType = document.getElementById("character_type");
        var characterName = characterType.options[characterType.selectedIndex].text;
        var actionType = document.getElementById("choose_action");
        var actionName = actionType.options[actionType.selectedIndex].text;
        var iterations = document.getElementById('player_iterations').value;
        var pos_x = document.getElementById('player_x').value*TILE_RESOLUTION;
        var pos_y = document.getElementById('player_y').value*TILE_RESOLUTION;

        var NPCType = document.getElementById("NPC_type");
        var NPCName = NPCType.options[NPCType.selectedIndex].text;
        var actionType_NPC = document.getElementById("choose_action_NPC");
        var actionName_NPC = actionType_NPC.options[actionType_NPC.selectedIndex].text;
        var NPC_iterations = document.getElementById('NPC_iterations').value;
        var NPC_x = document.getElementById('NPC_X').value*TILE_RESOLUTION;
        var NPC_y = document.getElementById('NPC_Y').value*TILE_RESOLUTION;

        console.log(characterName);
        console.log(NPCName);
        // set to the proper state

        if(NPCName == "Student" || characterName == "Student"){
            for( var i = 0; i < _scene.Student.length; ++i){
                _scene.Student[i].updateState(actionName_NPC);
                _scene.Student[i].currentSpriteFrame = 0;
                _scene.Student[i].x = NPC_x;
                _scene.Student[i].y = NPC_y;
                _scene.Student[i].tileX = document.getElementById('NPC_X').value;
                _scene.Student[i].tileY = document.getElementById("NPC_Y").value;
            }
        }

        if(characterName != "Student"){
            _scene[characterName].updateState(actionName);
            _scene[characterName].currentSpriteFrame = 0;
            _scene[characterName].x = pos_x;
            _scene[characterName].y = pos_y;
            _scene[characterName].tileX = document.getElementById("player_x").value;
            _scene[characterName].tileY = document.getElementById("player_y").value;
        }
    }
}
var gameEngine = new GameEngine();